import logging

from django.http import HttpResponse
from django.utils import timezone
from rest_framework import status
from rest_framework.views import APIView

from common.tools.money_cast import transforms_int
from common.views import get_obj
from common.wx.config import WxPayConf_service, WxPayConf_pub
from common.wx.pay import Notify_pub
from groupshopping.models import ShoppingGroup, ShoppingMem
from kill.models import KillRecord
from open.models import WxPayInfo, WxPublicMapShop
from order.models import Order, OrderProduct
from wehelp.models import KanJiaUserMaster

logger = logging.getLogger('qixiaobao')


class WxAppHooksView(APIView):
    """支付成功后回调"""
    PAY_SUCCESS = 1
    REFUND_SUCCESS = 2
    FAIL, SUCCESS = 'FAIL', 'SUCCESS'

    def post(self, request, *args, **kwargs):
        xml = request.body
        # 使用通用通知接口
        notify = Notify_pub()
        notify.saveData(xml)
        result = notify.getData()
        if result['return_code'] == self.FAIL:
            notify.setReturnParameter('return_code', self.FAIL)
            notify.setReturnParameter('return_msg', '通信错误')
        elif result['result_code'] == self.FAIL:
            notify.setReturnParameter('return_code', self.FAIL)
            notify.setReturnParameter('return_msg', result['err_code_des'])
        else:
            trade_type = result['trade_type']  # 交易类型
            app_id = result['appid']
            mch_id = result['mch_id']

            if 'sub_appid' in result or 'sub_mch_id' in result:
                app_id = result.get('sub_appid', '')
                mch_id = result.get('sub_mch_id', '')
                config = WxPayConf_service()
                notify.setConfig(config)
            else:
                pi = get_obj(WxPayInfo, app_id=app_id, mch_id=mch_id, status=WxPayInfo.STATUS_VALID)
                if not pi:
                    notify.setReturnParameter('return_code', self.FAIL)
                    return HttpResponse(notify.returnXml())

                config = WxPayConf_pub()
                config.APPID = app_id
                config.MCHID = mch_id
                config.KEY = pi.key
                notify.setConfig(config)
            # 验证签名，并回应微信。
            # 对后台通知交互时，如果微信收到商户的应答不是成功或超时，微信认为通知失败，
            # 微信会通过一定的策略（如30分钟共8次）定期重新发起通知，
            # 尽可能提高通知的成功率，但微信不保证通知最终能成功
            if not notify.checkSign():
                logger.debug('check_sign error')
                notify.setReturnParameter('return_code', self.FAIL)  # 返回状态码
                notify.setReturnParameter('return_msg', '签名失败')  # 返回信息
            else:
                out_trade_no = result['out_trade_no']  # 商户系统的订单号，与请求一致。
                attach = result.get('attach', 'product')
                total_fee = transforms_int(result['total_fee'], 0)  # 总金额
                transaction_id = result['transaction_id']  # 微信支付订单号
                time_end = result['time_end']  # 支付完成时间
                if not trade_type == 'JSAPI':
                    notify.setReturnParameter('return_code', self.FAIL)
                    return HttpResponse(notify.returnXml())

                # 检查订单号是否已存在,以及业务代码(业务代码注意重入问题)
                http_code, order, pi = before_check(out_trade_no, total_fee, transaction_id, app_id, mch_id)
                if not http_code:
                    if attach == 'product':
                        http_code = product_pay_success(order)
                    elif attach == 'groupshopping':
                        http_code = groupshopping_pay_success(order)
                    elif attach == 'kill':
                        http_code = kill_pay_success(order)
                    elif attach == "kill_deposit":
                        pass
                    elif attach == 'kanjia':
                        http_code = kanjia_pay_success(order)
                    else:
                        http_code = status.HTTP_404_NOT_FOUND
                if http_code == status.HTTP_200_OK:
                    notify.setReturnParameter('return_code', self.SUCCESS)
                else:
                    notify.setReturnParameter('return_code', self.FAIL)
        return HttpResponse(notify.returnXml())


def before_check(order_id, amount, third_id, app_id, mch_id):
    order = ''
    pi = ''
    try:
        order = Order.objects.get(id=order_id, status=Order.STATUS_VALID)
    except Order.DoesNotExist:
        return status.HTTP_500_INTERNAL_SERVER_ERROR, order, pi
    if order.pay_type == Order.SELF_PUB:
        if hasattr(order.shop, 'public_shop'):
            try:
                pi = WxPayInfo.objects.get(app_id=order.shop.public_shop.app_id, status=WxPayInfo.STATUS_VALID)
                if not pi.app_id == app_id or not pi.mch_id == mch_id:
                    return status.HTTP_400_BAD_REQUEST, order, pi
            except WxPayInfo.DoesNotExist:
                return status.HTTP_404_NOT_FOUND, order, pi
        else:
            return status.HTTP_404_NOT_FOUND, order, pi
    elif order.pay_type in (Order.PAY_WX_SERVICE,):
        pi = get_obj(WxPublicMapShop, shop=order.shop, mch_id=mch_id, status=WxPublicMapShop.STATUS_VALID)
        if not pi:
            return status.HTTP_404_NOT_FOUND, order, pi

    if not order.state == Order.STATE_WAIT_PAY:
        return status.HTTP_200_OK, order, pi
    # 1. 判断订单金额
    if not order.amount == amount:
        return status.HTTP_500_INTERNAL_SERVER_ERROR, order, pi

    order.fact = amount
    order.state = Order.STATE_SEND
    order.third_id = third_id
    t_now = timezone.now()
    order.payed_time = t_now
    order.send_time = t_now
    order.save()
    return '', order, pi


def order_complete(order):
    if order.state in [Order.STATE_PAYED, Order.STATE_SEND]:
        order.state = Order.STATE_COMPLETE
        order.complete_time = timezone.now()
        order.save()


def kanjia_pay_success(order, debug=False):
    """砍价支付成功"""
    product = None
    for order_product in OrderProduct.objects.filter(order=order, type=OrderProduct.OP_BUY,
                                                     status=OrderProduct.STATUS_VALID):
        order_product.fact = order_product.amount
        order_product.save()
        product = order_product.content_object
        if product.pre_sale - order_product.number < 0:
            product.pre_sale = 0
        else:
            product.pre_sale -= order_product.number
        product.sale += order_product.number
        product.save()

    # 设置砍价成员
    try:
        master = KanJiaUserMaster.objects.get(user=order.user, info=product,
                                              real_price=product.price_discount,
                                              status=KanJiaUserMaster.STATUS_VALID)
        if master.order and master.order.id != order.id and not master.refund and master.order.state == Order.STATE_WAIT_PAY:
            master.order = order
            master.save()
    except KanJiaUserMaster.DoesNotExist:
        pass
    order_complete(order)
    if debug:
        return status.HTTP_200_OK
    return status.HTTP_200_OK


def groupshopping_pay_success(order, debug=False):
    try:
        order_product = OrderProduct.objects.get(order=order, status=OrderProduct.STATUS_VALID)
    except OrderProduct.DoesNotExist:
        return status.HTTP_404_NOT_FOUND

    order_product.fact = order_product.amount
    order_product.save()
    shopping_group = order_product.content_object  # 对应shopping_group

    result = {'status': 0, 'detail': 'success'}
    if not isinstance(shopping_group, ShoppingGroup):
        return status.HTTP_404_NOT_FOUND
    tuanshopping = shopping_group.info
    try:
        member = ShoppingMem.objects.get(order=order, user=order.user, info=tuanshopping)
        member.status = ShoppingMem.STATUS_VALID
        member.save()
        if not shopping_group.group_state == ShoppingGroup.GROUP_DOING:
            result = {'status': 3, 'detail': '拼团状态为{}'.format(shopping_group.get_group_state_display())}
    except ShoppingMem.DoesNotExist:
        result = {'status': 1, 'detail': '参团人不存在'}

    if shopping_group is None:
        result = {'status': 1, 'detail': '团组不存在'}

    if order.order_type == Order.ORDER_TUANSHOPPING_MASTER:
        if not shopping_group.info.get_inventory_status():
            result = {'status': 3, 'detail': '活动已满'}
        shopping_group.status = ShoppingGroup.STATUS_VALID
        shopping_group.save()

    order_complete(order)

    if result['status'] == 0:
        # 正常开团/参团
        if order.order_type == Order.ORDER_TUANSHOPPING_MASTER:
            shopping_group.group_state = ShoppingGroup.GROUP_DOING
        elif order.order_type == Order.ORDER_TUANSHOPPING_GROUP:
            shopping_group.number += 1
            if shopping_group.number >= shopping_group.model_number:
                shopping_group.group_state = shopping_group.GROUP_SUCCESS
                # 每成功一个团减一个库存
                shopping_group.info.sale += 1
                shopping_group.info.save()
        else:
            return status.HTTP_404_NOT_FOUND
        shopping_group.save()
    else:
        # 此处需要退款操作
        pass
    return status.HTTP_200_OK


def product_pay_success(order, debug=False):
    product = None
    for order_product in OrderProduct.objects.filter(order=order, type=OrderProduct.OP_BUY,
                                                     status=OrderProduct.STATUS_VALID):
        order_product.fact = order_product.amount
        order_product.save()
        product = order_product.content_object
        # if product.pre_sale - order_product.number < 0:
        #     product.pre_sale = 0
        # else:
        #     product.pre_sale -= order_product.number
        # product.sale += order_product.number
        product.inventory -= order_product.number
        product.save()
    order_complete(order)
    return status.HTTP_200_OK


def kill_pay_success(order, debug=False):
    product = None
    for order_product in OrderProduct.objects.filter(order=order, type=OrderProduct.OP_BUY,
                                                     status=OrderProduct.STATUS_VALID):
        order_product.fact = order_product.amount
        order_product.save()
        product = order_product.content_object
        if product.pre_sale - order_product.number < 0:
            product.pre_sale = 0
        else:
            product.pre_sale -= order_product.number
        product.sale += order_product.number
        product.save()
        KillRecord.objects.create(
            shop_id=product.shop_id,
            user=order.user,
            name=order.receiver.name,
            phone=order.receiver.phone,
            info=product,
            order_id=order.id,
            status=KillRecord.STATUS_VALID
        )
    order_complete(order)
    return status.HTTP_200_OK
